/* eslint-env node */

import Promise from 'bluebird';
import { spawn, spawnSync } from 'child_process';
import knexfile from './knexfile';

// pt-online-schema-change's config
let { stdout: ptOscPath } = spawnSync('which', ['pt-online-schema-change'], {
  encoding: 'utf-8',
});
if (ptOscPath) {
  ptOscPath = ptOscPath.trim();
  console.log('Use pt-online-schema-change for table\'s modification.');
} else {
  console.log('Use knex for table\'s modification.');
}

// mysql's config TODO 从命令行读取env
const env = process.env.NODE_ENV || 'development';
const {
  host,
  user,
  password,
  database,
} = knexfile[env].connection;

/**
 * 更新表的统一入口，根据可执行路径是否存在pt-online-schema-change，选择使用pt-online-schema-change 或 knex 来实现DB变更
 *
 * alterClause 举例：
 * 1. 添加列: ADD COLUMN f_id int default 0
 * 2. 修改列: CHANGE COLUMN pad f_pad varchar(60) NOT NULL DEFAULT ''
 * 3. 删除列: DROP COLUMN f_pad
 * 4. 添加索引: ADD KEY idx_corpid_userid(f_corp_id,f_user_id)
 * 5. 删除索引: DROP KEY idx_corpid_userid
 *
 * @param {Object} knex knex对象
 * @param {String} table 表的名称
 * @param {String} alterClause 表变更语句
 * @param {Boolean} forceNoCheck 【慎用】确认字段类型或名称变更可以正常工作后，打开这个开关，不然字段变更类的操作都会失败
 * @param {Boolean} forceKnex 是否强制使用Knex（即Mysql5.6的Online DDL）
 */
function modifyTable(knex, table, alterClause,
  { forceNoCheck = false, forceKnex = false } = {}) {
  if (!forceKnex && ptOscPath) {
    return new Promise((resolve, reject) => {
      let ptOscOptions = [`--host=${host}`, `--user=${user}`, '--execute',
        `D=${database},t=${table}`, `--alter=${alterClause}`,
      ];
      if (password) {
        ptOscOptions.push(`--password=${password}`);
      }
      if (forceNoCheck) {
        ptOscOptions.push('--no-check-alter');
      }

      let oscProcess = spawn(ptOscPath, ptOscOptions);
      oscProcess.stdout.on('data', (data) => {
        console.log(`${data}`);
      });
      oscProcess.stderr.on('data', (data) => {
        console.log(`${data}`);
      });
      oscProcess.on('close', (code) => {
        if (code === 0) {
          resolve();
        } else {
          reject();
        }
      });
    });
  } else {
    return knex.schema.raw(`ALTER TABLE ${table} ${alterClause}`);
  }
}

export default {
  modifyTable,
};
